home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / slip / cslip-2.6 / tip / page.c.leres < prev    next >
Encoding:
Text File  |  1990-05-30  |  6.4 KB  |  303 lines

  1. #ifndef lint
  2. static char *sccsid = "@(#)page.c    1.4    MS/ACF    89/05/08";
  3. #endif
  4.  
  5. /*
  6.  *    tip/page.c    (Douglas Kingston, Morgan Stanley & Co.)
  7.  *
  8.  *    This file contains code to send alphanumeric pages via
  9.  *    dialup paging services that support "Remote Entry Device
  10.  *    Protocol" (aka "IXO").  These services typically send to
  11.  *    devices like the Motorola PMR-2000 pager.
  12.  *
  13.  *    This module is designed to use the ACK/NAK packet protocol
  14.  *    to ensure the highest likelyhood of correct delivery of the
  15.  *    message.  The packets are checksummed and all messages are
  16.  *    acknowledged by the receiver.
  17.  *
  18.  *    To use this facility, tip must be called with the -p option,
  19.  *    a system name (what system to dial up) and finally a data
  20.  *    string which contains 3 items:  A login code/password, a list
  21.  *    pager id's to receive the message, and the message text.
  22.  *    The three fields are separated by tabs.  The pager id field
  23.  *    is further subdivided into a list of pager ids by commas.
  24.  *
  25.  *    For example:
  26.  *    tip -p metro "12345678\t20001,20002\tPlease call the office."
  27.  *
  28.  *    Would call the system called "metro" as listed in /etc/remote
  29.  *    and login with the ID 12345678.  The message "Please call
  30.  *    the office." would be sent to pagers 20001 and 20002.
  31.  *
  32.  *    This code has been tested only on the Metromedia Paging Services
  33.  *    system around New York City, though it should work on other
  34.  *    similiar systems.
  35.  *
  36.  *    Douglas Kingston
  37.  *    Morgan Stanley & Co. (19th Floor)
  38.  *    1251 Avenue of the Americas
  39.  *    NY, NY, 10020
  40.  */
  41.  
  42. #include <stdio.h>
  43. #include <ctype.h>
  44. #include <signal.h>
  45. #include <sys/time.h>
  46. #include "tip.h"
  47.  
  48. #define WRITE_DELAY 40        /* ms between each character written to modem */
  49.  
  50. static int lread(), lputc();
  51. static void errputc(), errputs();
  52. static char *pgsend(), *pgrecv();
  53.  
  54. sendpage(data)
  55.     char *data;
  56. {
  57.     char *cp, *pager, *message;
  58.     char buf[65 + 2];        /* 65 char max sized msg + CR + EOS */
  59.  
  60.     if (vflag)
  61.         fputs("[Connected]\n", stderr);
  62.  
  63.     /* Extract pager id */
  64.     if (pager = index(data, '\t')) {
  65.         *pager = '\0';
  66.         ++pager;
  67.     } else {
  68.         fputs("[Bad paging data: \"", stderr);
  69.         errputs(data);
  70.         fputs("\"]\n", stderr);
  71.         return(1);
  72.     }
  73.  
  74.     /* Extract message */
  75.     if (message = index(pager, '\t')) {
  76.         *message = '\0';
  77.         ++message;
  78.     } else
  79.         message = "[Message not specified]";
  80.  
  81.  
  82.     /* Send initial CR */
  83.     if (cp = pgsend("\r")) {
  84.         (void)fprintf(stderr, "[Failed to send CR: %s]\n", cp);
  85.         return(1);
  86.     }
  87.  
  88.     /* Look for options line */
  89.     /*
  90.      * "METROCAST Page Input"
  91.      * "ENTER CONTROL-NUMBER TO PAGE OR (CR) FOR OPTIONS >"
  92.      */
  93.     if (cp = pgrecv("OPTIONS >", 5)) {
  94.         (void)fprintf(stderr,
  95.             "[Failed to find options prompt: %s]\n", cp);
  96.         return(1);
  97.     }
  98.  
  99.     /* Send target pager id */
  100.     /* XXX Need to handle multiple pagers */
  101.     (void)sprintf(buf, "%s\r", pager);
  102.     if (cp = pgsend(buf)) {
  103.         (void)fprintf(stderr, "[Failed to send pager id: %s]\n", cp);
  104.         return(1);
  105.     }
  106.  
  107.     /* Look for page prompt */
  108.     /*
  109.      * "ENTER Message to 250 Characters; End with CR;"
  110.      * "MAX Length Per/Page Currently 65."
  111.      * ">"
  112.      */
  113.     if (cp = pgrecv(">", 5)) {
  114.         (void)fprintf(stderr, "[Failed to find message prompt: %s]\n",
  115.             cp);
  116.         return(1);
  117.     }
  118.  
  119.     /* Blast it out */
  120.     /* XXX need to check for max length/truncate */
  121.     (void)sprintf(buf, "%.*s\r", sizeof(buf) - 2, message);
  122.     if (cp = pgsend(buf)) {
  123.         (void)fprintf(stderr, "[Failed to send message: %s]\n", cp);
  124.         return(1);
  125.     }
  126.  
  127.     /* Make sure it was "delivered" */
  128.     /* "1 Page(s) Placed (1 total)" */
  129.     if (cp = pgrecv("1 Page(s) Placed", 5)) {
  130.         (void)fprintf(stderr, "[Error in delivery: %s]\n", cp);
  131.         return(1);
  132.     }
  133.  
  134.     /* Kiss it goodbye */
  135.     (void) pgsend("\033");
  136.     return(0);
  137. }
  138.  
  139. static char *
  140. pgsend(cp)
  141.     register char *cp;
  142. {
  143.     register char c;
  144.     struct timeval t;
  145.  
  146.  
  147.     if (debug)
  148.         fputs("=> \"", stderr);
  149.     t.tv_sec = 0;
  150.     t.tv_usec = WRITE_DELAY * 1000000;
  151.     while (*cp) {
  152.         c = *cp++;
  153.         if (lputc(c) != 1)
  154.             return("write error to remote site");
  155.         if (debug)
  156.             errputc(c);
  157.         (void) select(32, 0, 0, 0, &t);
  158.     }
  159.     if (debug)
  160.         fputs("\"\n", stderr);
  161.     return(0);
  162. }
  163.  
  164. static char *
  165. pgrecv(want, secs)
  166.     char *want;
  167.     int secs;
  168. {
  169.     register int i, j, n, size;
  170.     static char buf[128];
  171.     char *endstr = "\"\n";
  172.     
  173.     size = strlen(want);
  174.     if (size >= sizeof(buf)) {
  175.         (void)sprintf(buf, "pgrecv: size too big  (%d >= %d)",
  176.             size, sizeof(buf));
  177.         return(buf);
  178.     }
  179.     if (debug) {
  180.         fputs("<? \"", stderr);
  181.         errputs(want);
  182.         fputs("\"\n<= \"", stderr);
  183.     }
  184.     for (i = 0; i < size; ) {
  185.         /* Read as much as we can, handle timeout and errors */
  186.         if ((n = lread(FD, &buf[i], size - i, (u_int)secs)) < 0) {
  187.             if (debug)
  188.                 fputs(endstr, stderr);
  189.             (void)sprintf(buf, "pgrecv: lread(1): %s\n",
  190.                 strerror(errno));
  191.             return(buf);
  192.         } else if (n == 0) {
  193.             if (debug)
  194.                 fputs(endstr, stderr);
  195.             return("pgrecv: timeout (1)");
  196.         }
  197.  
  198.         /* Gag, ANYP is all it's cracked up to be */
  199.         for (j = i; j < i + n; ++j)
  200.             buf[j] &= 0177;
  201.         if (debug)
  202.             for (j = i; j < i + n; ++j)
  203.                 errputc(buf[j]);
  204.         i += n;
  205.         buf[i] = '\0';
  206.     }
  207.     i = size - 1;
  208.     while (strncmp(buf, want, size)) {
  209.         bcopy(buf + 1, buf, size);
  210.         if ((n = lread(FD, &buf[i], 1, (u_int)secs)) < 0) {
  211.             if (debug)
  212.                 fputs(endstr, stderr);
  213.             (void)sprintf(buf, "pgrecv: lread(2): %s\n",
  214.                 strerror(errno));
  215.             return(buf);
  216.         } else if (n == 0) {
  217.             if (debug)
  218.                 fputs(endstr, stderr);
  219.             return("pgrecv: timeout (2)");
  220.         }
  221.         buf[i] &= 0177;
  222.         if (debug)
  223.             errputc(buf[i]);
  224.     }
  225.     if (debug)
  226.         fputs(endstr, stderr);
  227.     return(0);
  228. }
  229.  
  230. static int
  231. lread(f, buf, len, secs)
  232.     int f;
  233.     char *buf;
  234.     int len;
  235.     u_int secs;
  236. {
  237.     register int n;
  238.     struct timeval t;
  239.     int readfds;
  240.  
  241.     t.tv_sec = secs;
  242.     t.tv_usec = 0;
  243.     readfds = 1 << FD;
  244.     if ((n = select(f + 1, &readfds, 0, 0, &t)) <= 0)
  245.         return(n);
  246.     return(read(f, buf, len));
  247. }
  248.  
  249. static int
  250. lputc(c)
  251.     char c;
  252. {
  253.     struct timeval t;
  254.  
  255.     if (write(FD, &c, 1) != 1)
  256.         return(-1);
  257.     t.tv_sec = 0;
  258.     t.tv_usec = WRITE_DELAY * 1000000;
  259.     (void) select(32, 0, 0, 0, &t);
  260.     return(1);
  261. }
  262.  
  263. static void
  264. errputs(s)
  265.     register char *s;
  266. {
  267.     while (*s)
  268.         errputc(*s++);
  269. }
  270.  
  271. static void
  272. errputc(c)
  273.     char c;
  274. {
  275.     if (c & ~ 0177) {
  276.         putc('M', stderr);
  277.         putc('-', stderr);
  278.         c &= 0177;
  279.     }
  280.     if (c < 0x20 || c == 0177) {
  281.         if (c == '\b') {
  282.             putc('\\', stderr);
  283.             putc('b', stderr);
  284.         } else if (c == '\f') {
  285.             putc('\\', stderr);
  286.             putc('f', stderr);
  287.         } else if (c == '\n') {
  288.             putc('\\', stderr);
  289.             putc('n', stderr);
  290.         } else if (c == '\r') {
  291.             putc('\\', stderr);
  292.             putc('r', stderr);
  293.         } else if (c == '\t') {
  294.             putc('\\', stderr);
  295.             putc('t', stderr);
  296.         } else {
  297.             putc('^', stderr);
  298.             putc(c ^ 0x40, stderr);    /* DEL to ?, others to alpha */
  299.         }
  300.     } else
  301.         putc(c, stderr);
  302. }
  303.